package com.tom.architect.party4.day34.retrofit;

import android.util.Log;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import okhttp3.OkHttpClient;


/**
 * implementation 'com.squareup.okhttp3:okhttp:3.9.0'
 */
public class Retrofit {
    final String baseUrl;
    final okhttp3.Call.Factory callFactory;
    // 缓存ServiceMethod
    private Map<Method, ServiceMethod> serviceMethodMapCache = new ConcurrentHashMap<>();

    public Retrofit(Builder builder) {
        this.baseUrl = builder.baseUrl; // builder赋值
        this.callFactory = builder.callFactory;
    }

    // 创建实例对象。重点1 方法
    // 方法泛型，传出去T，方法泛型必须要声明<T>
    public <T> T create(Class<T> service) { // 传入ServiceClass。
        // validateServiceInterface(): 检验，是不是一个接口。也不能让他继承其他的子接口。
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 每执行一个方法，都会进入invoke()。
                        Log.e("TAG", "method invoke: " + method.getName());
                        // 判断是不是Object的方法。
                        if (method.getDeclaringClass() == Object.class) {
                            // 直接执行Object的方法。
                            return method.invoke(this, args);
                        }

                        // 解析参数的注解
                        // 2.封装okHttpCall
                        ServiceMethod serviceMethod = loadServiceMethod(method);
                        OkHttpCall okHttpCall = new OkHttpCall(serviceMethod, args);
                        return okHttpCall;
                    }
                });
    }

    private ServiceMethod loadServiceMethod(Method method) {
        // 享元设计模式，缓存复用。
        ServiceMethod serviceMethod = serviceMethodMapCache.get(method);
        if (serviceMethod == null) {
            // 解析参数的注解，方法的注解。
            // Builder设计模式：解析注解
            serviceMethod = new ServiceMethod.Builder(this, method).build();
            // 享元，对象复用
            serviceMethodMapCache.put(method, serviceMethod);
        }
        return serviceMethod;
    }

    // Builder设计模式，构建Retrofit
    public static class Builder {
        String baseUrl;
        okhttp3.Call.Factory callFactory;

        public Builder baseUrl(String baseUrl) {
            this.baseUrl = baseUrl;
            return this;
        }

        public Builder client(okhttp3.Call.Factory callFactory) {
            this.callFactory = callFactory;
            return this;
        }

        public Retrofit build() {
            if (callFactory == null) {
                callFactory = new OkHttpClient(); // 默认使用okHttpClient
            }
            return new Retrofit(this);
        }
    }

}
